home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 June / EnigmA AMIGA RUN 08 (1996)(G.R. Edizioni)(IT)[!][issue 1996-06][EARSAN CD VII].iso / earcd / gcc / ixemlsrc.lha / ixemul / library / __fstat.c < prev    next >
C/C++ Source or Header  |  1996-03-13  |  9KB  |  265 lines

  1. /*
  2.  *  This file is part of ixemul.library for the Amiga.
  3.  *  Copyright (C) 1991, 1992  Markus M. Wild
  4.  *
  5.  *  This library is free software; you can redistribute it and/or
  6.  *  modify it under the terms of the GNU Library General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2 of the License, or (at your option) any later version.
  9.  *
  10.  *  This library is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  *  Library General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU Library General Public
  16.  *  License along with this library; if not, write to the Free
  17.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *  __fstat.c,v 1.1.1.1 1994/04/04 04:30:08 amiga Exp
  20.  *
  21.  *  __fstat.c,v
  22.  * Revision 1.1.1.1  1994/04/04  04:30:08  amiga
  23.  * Initial CVS check in.
  24.  *
  25.  *  Revision 1.2  1993/11/05  21:49:59  mw
  26.  *  "grp/oth-perms,
  27.  *
  28.  *  Revision 1.1  1992/05/14  19:55:40  mwild
  29.  *  Initial revision
  30.  *
  31.  */
  32.  
  33. #define KERNEL
  34. #include <string.h>
  35. #include <stdio.h>
  36. #include "ixemul.h"
  37. #include "kprintf.h"
  38.  
  39. #ifndef ACTION_EXAMINE_FH
  40. #define ACTION_EXAMINE_FH 1034
  41. #endif
  42.  
  43. #ifndef ST_LINKDIR
  44. #define ST_ROOT        1
  45. #define ST_USERDIR    2
  46. #define ST_SOFTLINK    3    /* looks like dir, but may point to a file! */
  47. #define ST_LINKDIR    4    /* hard link to dir */
  48. #define ST_FILE        -3    /* must be negative for FIB! */
  49. #define ST_LINKFILE    -4    /* hard link to file */
  50. #define ST_PIPEFILE    -5    /* for pipes that support ExamineFH */
  51. #endif
  52.  
  53. /************************************************************************/
  54. /*                                                                      */
  55. /*    fstat() function.                                                 */
  56. /*                                                                      */
  57. /************************************************************************/
  58.  
  59. int
  60. __fstat(struct file *f)
  61. {
  62.   long len, pos;
  63.   struct FileInfoBlock *fib;
  64.   struct InfoData *info;
  65.   int omask;
  66.  
  67.   omask = syscall (SYS_sigsetmask, ~0);
  68.   __get_file (f);
  69.  
  70.   /* take special care of NIL:, /dev/null and friends ;-) */
  71.   if (HANDLER_NIL(f))
  72.     {
  73.       f->f_stb.st_mode = S_IFCHR | 0777;
  74.       f->f_stb.st_nlink = 1;
  75.       f->f_stb.st_blksize = ix.ix_fs_buf_factor * 512;
  76.       f->f_stb.st_blocks = 0;
  77.       goto end;
  78.     }
  79.  
  80.   info = alloca (sizeof (*info) + 2);
  81.   info = LONG_ALIGN (info);
  82.   fib  = alloca (sizeof (*fib) + 2);
  83.   fib  = LONG_ALIGN (fib);
  84.     
  85.   __wait_packet (&f->f_sp);
  86.   /* reset the error field */
  87.   LastError (f) = 0;
  88.  
  89.   /* we now have two possibilities.. either the filesystem understands the
  90.    * new ACTION_EXAMINE_FH packet, or we have to do some guesses at fields.. */
  91.   SendPacket2 (f, __rwport, ACTION_EXAMINE_FH, f->f_fh->fh_Arg1, CTOBPTR(fib));
  92.   __wait_packet (&f->f_sp);
  93.   if (LastResult(f))
  94.     {
  95.       int mode;
  96.  
  97.       f->f_stb.st_nlink = 1; /* always one link entry per file, unless... */
  98.       f->f_stb.st_amode = fib->fib_Protection;
  99.  
  100.       mode = 0;
  101.       if (!(fib->fib_Protection & FIBF_EXECUTE))
  102.         mode |= S_IXUSR;
  103.       else if (fib->fib_Protection & FIBF_SCRIPT)
  104.         mode |= S_IXUSR;
  105.       if (!(fib->fib_Protection & (FIBF_WRITE|FIBF_DELETE)))
  106.         mode |= S_IWUSR;
  107.       if (!(fib->fib_Protection & FIBF_READ))
  108.         mode |= S_IRUSR;
  109. #ifdef FIBF_GRP_EXECUTE
  110.       /* FIBF_GRP_EXECUTE requires at least OS3 headers */
  111.       if (fib->fib_Protection & FIBF_GRP_EXECUTE)
  112.         mode |= S_IXGRP;
  113.       if ((fib->fib_Protection & (FIBF_GRP_WRITE|FIBF_GRP_DELETE)) == (FIBF_GRP_WRITE|FIBF_GRP_DELETE))
  114.         mode |= S_IWGRP;
  115.       if (fib->fib_Protection & FIBF_GRP_READ)
  116.         mode |= S_IRGRP;
  117.       if (fib->fib_Protection & FIBF_OTR_EXECUTE)
  118.         mode |= S_IXOTH;
  119.       if ((fib->fib_Protection & (FIBF_OTR_WRITE|FIBF_OTR_DELETE)) == (FIBF_OTR_WRITE|FIBF_OTR_DELETE))
  120.         mode |= S_IWOTH;
  121.       if (fib->fib_Protection & FIBF_OTR_READ)
  122.         mode |= S_IROTH;
  123. #endif
  124.  
  125.       switch (fib->fib_DirEntryType)
  126.         {
  127.         case ST_LINKDIR:
  128.           f->f_stb.st_nlink++;  /* we never get more than a link count of two.. */
  129.         case ST_ROOT:
  130.         case ST_USERDIR:
  131.           mode |= S_IFDIR;
  132.           break;
  133.  
  134.         /* at the moment, we NEVER get this entry, since we can't get a lock
  135.          * on a symlink */
  136.         case ST_SOFTLINK:
  137.           mode |= S_IFLNK;
  138.           break;
  139.  
  140.     case ST_PIPEFILE:
  141.       /* don't use S_IFIFO, we don't have a mkfifo() call ! */
  142.       mode |= S_IFCHR;
  143.       break;
  144.  
  145.         case ST_LINKFILE:
  146.           f->f_stb.st_nlink ++;
  147.         case ST_FILE:
  148.         default:
  149.           mode |= S_IFREG;
  150.         }
  151.  
  152.       /* ARGLLLLL !!!
  153.          Some (newer, hi Bill Hawes ;-)) handlers support EXAMINE_FH, but
  154.          don't know yet about ST_PIPEFILE. So console windows claim they're
  155.          plain files... Until this problem is fixed in a majority of
  156.          handlers, do an explicit SEEK here to find those fakers.. */
  157.       LastError(f) = 0;
  158.       SendPacket3(f,__rwport,ACTION_SEEK,f->f_fh->fh_Arg1,0,OFFSET_CURRENT);
  159.       __wait_packet (&f->f_sp);
  160.       if (LastError (f))
  161.         mode = (mode & ~S_IFREG) | S_IFCHR;
  162.  
  163.       f->f_stb.st_mode = mode;
  164.  
  165.       /* support for annotated attributes (cool name ;-)) */
  166.       if (! strncmp (fib->fib_Comment, "!SP!", 4))
  167.         {
  168.           int sp_mode, sp_addr;
  169.  
  170.           if (sscanf (fib->fib_Comment + 4, "%x!%x", &sp_mode, &sp_addr) == 2)
  171.             f->f_stb.st_mode = sp_mode;
  172.         }
  173.   
  174.       /* some kind of a default-size for directories... */
  175.       f->f_stb.st_size = fib->fib_DirEntryType<0 ? fib->fib_Size : 1024; 
  176.       f->f_stb.st_handler = (long)f->f_fh->fh_Type;
  177.       f->f_stb.st_dev = (dev_t)f->f_stb.st_handler; /* trunc to 16 bit */
  178.       f->f_stb.st_ino = fib->fib_DiskKey; 
  179.       f->f_stb.st_atime =
  180.       f->f_stb.st_ctime =
  181.       f->f_stb.st_mtime = (8*365+2)*24*3600 + /* offset to unix-timesystem */
  182.                   fib->fib_Date.ds_Days * 24 * 60 * 60 +
  183.                   fib->fib_Date.ds_Minute * 60 +
  184.                   fib->fib_Date.ds_Tick/TICKS_PER_SECOND;
  185.       /* in a try to count the blocks used for filemanagement, we add one for
  186.        * the fileheader. Note, that this is wrong for large files, where there
  187.        * are some extension-blocks as well */
  188.       f->f_stb.st_blocks = fib->fib_NumBlocks + 1;
  189.     }
  190.   else
  191.     {
  192.       /* ATTENTION: see lseek.c for Bugs in Seek() and ACTION_SEEK ! */
  193.       /* seek to EOF */
  194.       SendPacket3 (f, __rwport, ACTION_SEEK, f->f_fh->fh_Arg1, 0, OFFSET_END);
  195.       __wait_packet (&f->f_sp);
  196.       pos = LastResult (f);
  197.       if (pos >= 0 && LastError (f) != ERROR_ACTION_NOT_KNOWN)
  198.         {
  199.           SendPacket3 (f, __rwport,ACTION_SEEK, f->f_fh->fh_Arg1, 
  200.                    pos, OFFSET_BEGINNING);
  201.           __wait_packet (&f->f_sp);
  202.           len = LastError (f) ? -1 : LastResult (f);
  203.         }
  204.       else
  205.         len = 0;
  206.  
  207.       bzero (&f->f_stb, sizeof(struct stat));
  208.  
  209.       f->f_stb.st_mode = ((len >= 0 && 
  210.                      /* !IsInteractive(CTOBPTR(f->f_fh)) */! f->f_fh->fh_Port)
  211.                      ? S_IFREG : S_IFCHR) | 0777;
  212.       f->f_stb.st_handler = (long)f->f_fh->fh_Type;
  213.       /* the following is a limited try to support programs, that assume that
  214.        * st_dev is always valid */
  215.       f->f_stb.st_dev = (dev_t)(long)(f->f_fh->fh_Type); /* truncate to 16 bit */
  216.       /* yet another kludge.. if we call this with different descriptors, we
  217.        * should get different inode numbers.. grmpf.. */
  218.       f->f_stb.st_ino = (ino_t)~(long)(f->f_fh);
  219.       f->f_stb.st_nlink = 1; /* for now no problem.. 2.0... */
  220.       /* len could be -1, if the device doesn't allow seeking.. */
  221.       f->f_stb.st_size = len >= 0 ? len : 0;
  222.       f->f_stb.st_atime =  
  223.       f->f_stb.st_mtime =
  224.       f->f_stb.st_ctime = syscall (SYS_time, 0);
  225.     }
  226.  
  227.   /* try to find out block size of device, hey postman, it's packet-time
  228.    * again:-)) */
  229.   /* make sure, the packet is not in use anymore */
  230.   __wait_packet(&f->f_sp);
  231.  
  232.   /* clear the info-structure. Since this packet is used by the console
  233.    * handler to transmit the window pointer, it actually answers the
  234.    * request, but doesn't set the not used fields to 0.. this gives HUGE
  235.    * block lengths :-)) */
  236.   bzero (info, sizeof(*info));
  237.   SendPacket1(f,__rwport,ACTION_DISK_INFO,CTOBPTR(info));
  238.   __wait_packet(&f->f_sp);
  239.  
  240.   f->f_stb.st_blksize = 0;
  241.   if (LastResult (f) && info->id_BytesPerBlock)
  242.     {
  243.       f->f_stb.st_blksize = info->id_BytesPerBlock;
  244.       if (!IsInteractive(CTOBPTR(f->f_fh)) && S_ISREG(f->f_stb.st_mode))
  245.     f->f_stb.st_blksize *= ix.ix_fs_buf_factor;
  246.       if (! f->f_stb.st_blocks) 
  247.     f->f_stb.st_blocks = ((f->f_stb.st_size + info->id_BytesPerBlock - 1) 
  248.                     / info->id_BytesPerBlock);
  249.     }
  250.  
  251.   if (! f->f_stb.st_blksize) 
  252.     {
  253.       f->f_stb.st_blksize = 512;
  254.       f->f_stb.st_blocks = (f->f_stb.st_size + 511) >> 9;
  255.     }
  256.  
  257. end:
  258.   /* reset error of packet. write() would fail if not */
  259.   LastResult(f) = 0;
  260.  
  261.   __release_file (f);
  262.   syscall (SYS_sigsetmask, omask);
  263.   return 0;
  264. }
  265.